<template>
  <a-tree
    class="tree"
    :key="treeKey"
    draggable
    block-node
    :defaultExpandAll="true"
    :show-line="{ showLeafIcon: false }"
    :tree-data="gData"
    :fieldNames="{ title: 'title', key: 'id' }"
    @dragenter="onDragEnter"
    @dragstart="onDragStart"
    @drop="onDrop"
    @mouseenter="handleMouseEnter"
    @mouseleave="handleMouseLeave"
  >
    <template #switcherIcon="{ switcherCls }"
      ><down-outlined :class="switcherCls"
    /></template>
    <template v-slot:title="nodeData">
      <!-- 树节点编辑状态 -->
      <div v-if="nodeData.editStatus == '1'" @mousedown.stop>
        <tree-node-edit
          :node="nodeData"
          :item-data="props.itemData"
          @node-change="treeNodeChange"
        />
      </div>
      <div v-else @mousedown.stop>
        <span>{{ nodeData.title }}</span>
        <a-button-group
          v-if="hoverNode && nodeData.id === hoverNode.id"
          style="float: right; padding: 5px 2px 0px 2px"
        >
          <plus-circle-outlined
            class="button-class"
            @click="addClick(nodeData)"
          />
          <edit-outlined class="button-class" @click="editClick(nodeData)" />
          <delete-outlined
            class="button-class"
            @click="deleteClick(nodeData)"
          />
          <iconfont style="font-size: 15px" name="#icon-tuodong" />
        </a-button-group>
      </div>
    </template>
  </a-tree>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
import { message } from 'ant-design-vue'
import { useDataSourceManager, useDataSource } from './provide-context.js'
import iconfont from '@/components/iconfont.vue'
import { DownOutlined } from '@ant-design/icons-vue'
import type {
  AntTreeNodeDragEnterEvent,
  AntTreeNodeDropEvent,
  TreeProps,
} from 'ant-design-vue/es/tree'
import TreeNodeEdit from './tree-node-edit.vue'
import {
  PlusCircleOutlined,
  EditOutlined,
  DeleteOutlined,
  HolderOutlined,
} from '@ant-design/icons-vue'
import {
  addNode,
  renameNode,
  publishProject,
  folderResort,
} from '@/api/catalog-personal'
/**
 * 全局数据
 */
let { update } = useDataSourceManager()

// 定义事件
let emit = defineEmits(['deleteNode', 'resetAdd'])
// 当前悬停的节点
let hoverNode = ref(null)
// 用于强制树节点重新渲染
const treeKey = ref(0)
/**
 * 外部参数
 */
let props = defineProps({
  itemData: {
    type: Object,
    default: () => {},
  },
})
let expandedKeys = ref([]) //  v-model:expanded-keys="expandedKeys"
type TreeDataItem = TreeProps['treeData'][number]
let gData = ref()

// 编辑状态禁止拖动
function onDragStart({ event, node }) {
  // console.log(event, node)
  let editStatus = ref(node?.editStatus)
  if (editStatus.value && editStatus.value == '1') {
    event.preventDefault()
    return
  }
}
// dataSource更新后刷新tree
watch(
  () => props.itemData.children,
  newTreeData => {
    gData.value = props.itemData.children
  },
  { deep: true, immediate: true },
)

const onDragEnter = (info: AntTreeNodeDragEnterEvent) => {
  // console.log(info)
  // expandedKeys 需要展开时
  // expandedKeys.value = info.expandedKeys;
}

const onDrop = (info: AntTreeNodeDropEvent) => {
  // console.log(info)

  // 只允许同级拖曳——拖曳前后同父节点

  const node = info.node //目标节点
  const dragNode = info.dragNode // 拖动节点
  const dragNodeData = dragNode.dataRef
  const nodeData = node.dataRef

  const dropKey = info.node.id
  const dragKey = info.dragNode.id
  const dropPos = info.node.pos.split('-')
  const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1])
  // console.log(dragKey, dropKey, dropPosition, info.dropToGap)
  // console.log(dragNodeData.parentId, nodeData.parentId, nodeData.id)

  if (!info.dropToGap && dragNodeData.parentId != nodeData.id) {
    // 移动到其他树枝 且不是对方子集 为了放开同级顶部
    message.warning('只能在同级排序')
    return false
  } else if (
    (info.node.children || []).length > 0 && // Has children
    info.node.expanded && // Is expanded
    dropPosition === 1 // On the bottom gap
  ) {
    message.warning('请重新拖拽')
  }
  // else if (dropPos.length == 2 && info.dropToGap) {
  //   message.warning('不能移动到最顶级')
  //   return false
  // }
  else if (dragNodeData.parentId !== nodeData.parentId && dropPosition === 1) {
    // 为了放开同级顶部 dropPosition=1：移动到和dropKey的平级，并在其下面
    message.warning('只能同级排序')
    return false
  }

  const loop = (
    data: TreeProps['treeData'],
    id: string | number,
    callback: any,
  ) => {
    data.forEach((item, index) => {
      if (item.id === id) {
        return callback(item, index, data)
      }
      if (item.children) {
        return loop(item.children, id, callback)
      }
    })
  }
  const data = [...gData.value]

  // Find dragObject
  let dragObj: TreeDataItem
  loop(
    data,
    dragKey,
    (item: TreeDataItem, index: number, arr: TreeProps['treeData']) => {
      arr.splice(index, 1)
      dragObj = item
    },
  )
  if (!info.dropToGap) {
    // Drop on the content
    loop(data, dropKey, (item: TreeDataItem) => {
      item.children = item.children || []
      /// where to insert 示例添加到头部，可以是随意位置
      item.children.unshift(dragObj)
    })
  } else if (
    (info.node.children || []).length > 0 && // Has children
    info.node.expanded && // Is expanded
    dropPosition === 1 // On the bottom gap
  ) {
    loop(data, dropKey, (item: TreeDataItem) => {
      item.children = item.children || []
      // where to insert 示例添加到头部，可以是随意位置
      item.children.unshift(dragObj)
    })
  } else {
    let ar: TreeProps['treeData'] = []
    let i = 0
    loop(
      data,
      dropKey,
      (_item: TreeDataItem, index: number, arr: TreeProps['treeData']) => {
        ar = arr
        i = index
      },
    )
    if (dropPosition === -1) {
      ar.splice(i, 0, dragObj)
    } else {
      ar.splice(i + 1, 0, dragObj)
    }
  }
  gData.value = data

  // 获取排序后在新treedata中的sort
  let params = []
  let sort = 1
  let parentId = info?.dragNode?.parentId

  if (parentId && parentId != props.itemData.id) {
    let parentNode = getNodeById(gData.value, parentId)
    console.log(parentNode)
    parentNode.children.forEach(item => {
      params.push({ id: item.id, sort })
      sort = sort + 1
    })
  } else {
    gData.value.forEach(item => {
      params.push({ id: item.id, sort })
      sort = sort + 1
    })
  }
  // 保存和发布拖动
  saveSortPublish(params)
}
// 保存和发布
async function saveSortPublish(params) {
  loading.value = true
  try {
    await folderResort(params)
    if (props.itemData.publishedStatus == 1) {
      // 已发布的项目同级移动之后立即发布
      let paramsPublish = {
        prjId: props.itemData.id,
      }
      await publishProject(paramsPublish)
    }
    await update()
    loading.value = false
  } catch (e) {
    loading.value = false
  }
}

/**
 * 树节点功能操作
 */
// 根据节点id在树上查找节点
function getNodeById(data, id) {
  for (let i = 0; i < data.length; i++) {
    if (data[i].id === id) {
      return data[i]
    }
    if (data[i].children) {
      const foundNode = getNodeById(data[i].children, id)
      if (foundNode) {
        return foundNode
      }
    }
  }
  return null
}
// 新增子集
function addClick(node) {
  node.children.unshift({
    parentId: node.id,
    editStatus: '1',
  })
  // 展开节点
  let parentNode = getNodeById(gData.value, node.id)
  parentNode.expanded = true
  treeKey.value += 1
}
// 编辑节点名称
function editClick(nodeData) {
  let currentNode = getNodeById(gData.value, nodeData.id)
  currentNode.editStatus = '1'
}
// 删除节点
function deleteClick(node) {
  emit('deleteNode', node)
}

// 树节点改动回调事件
let loading = ref(false)
async function treeNodeChange({ event, node, name, key = null }) {
  // console.log(event, node, name, gData)

  if (event == 'cancel') {
    if (key == 'edit') {
      // 编辑-恢复节点显示
      let currentNode = getNodeById(gData.value, node.id)
      currentNode.editStatus = '0'
    } else if (key == 'add') {
      // 新增-取消当前新增节点
      if (node.parentId == props.itemData.id) {
        // 添加的是根节点
        // 更新父组件props的值
        emit('resetAdd')
      } else {
        let parentNode = getNodeById(gData.value, node.parentId)
        parentNode.children.shift()
      }
    }
  } else if (event == 'edit') {
    loading.value = true
    try {
      let params = {
        id: node.id,
        newFolderName: name,
      }
      await renameNode(params)

      if (props.itemData.publishedStatus == 1) {
        // 已发布的项目 修改节点名之后立即发布
        let paramsPublish = {
          prjId: props.itemData.id,
        }
        await publishProject(paramsPublish)
      }
      await update()
      loading.value = false
      message.success('修改成功。')
    } catch (e) {
      loading.value = false
    }
  } else if (event == 'add') {
    loading.value = true
    try {
      let params = {
        parentId: node.parentId,
        folderName: name,
      }
      console.log(params)
      await addNode(params)
      await update()
      loading.value = false
      message.success('新建成功。')
    } catch (e) {
      loading.value = false
    }
  }
}
// 鼠标悬停显隐按钮
const handleMouseEnter = info => {
  hoverNode.value = info.node.dataRef
}
const handleMouseLeave = () => {
  hoverNode.value = null
}
</script>
<style scoped lang="less">
.button-class {
  margin-right: 5px;
  // color: #0086ff; //#dceffe
  color: #3d6d99;
}
</style>
